// 使用GNU用户界面
#define _GNU_SOURCE

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <regex.h>

// 输出字符串中指定范围内的字符
void print_substr(const char* s, size_t __start, size_t __end);

int main (int argc, char** argv)
{
    // 正则缓存
    regex_t pat_buf;
    // 匹配寄存器
    struct re_registers regs;
    const char *p_str = NULL;
    const char *err_code = NULL;
    size_t offset = 0;
    int pos = 0;

    // 正则表达式
    char* pat_str = "([0-9]+) (apples|oranges)";
    // 被匹配字符串
    char* str = "I have 20 apples and 34 oranges.";

    // 初始化
    memset(&pat_buf, 0, sizeof(regex_t));
    re_set_syntax(RE_SYNTAX_EGREP);

    // 编译正则表达式
    err_code = re_compile_pattern(pat_str, strlen(pat_str), &pat_buf);
    if(err_code != NULL)
    {
        printf("erro: %s\n", err_code);
        regfree(&pat_buf);
        exit(EXIT_FAILURE);
    }

    // 变量赋初值
    offset = 0;
    // 循环正则搜索
    do
    {
        // 字符串偏移
        p_str = str + offset;
        /* puts(p_str); */

        // 正则搜索
        pos = re_search(&pat_buf, p_str, strlen(p_str),
                        0, strlen(p_str), &regs);

        if(pos < 0) // 未找到，退出循环
        {
            break;
        }
        else
        {
            print_substr(p_str, regs.start[0], regs.end[0]);
            // 下一次查找开始位置
            offset += regs.end[0];
            continue;
        }
    }while(1);

    // 释放空间
    regfree(&pat_buf);
    // 匹配寄存器成员需要单独释放
    free(regs.start);
    free(regs.end);

    return 0;
}

/* 输出字符串中指定范围的字符 */
void print_substr(const char* s, size_t __start, size_t __end)
{
    int i;

    if(s == NULL)
    {
        return;
    }

    for(i = __start; i < __end; ++i)
    {
        putchar(s[i]);
    }

    putchar('\n');
}
